Skip to content

feat(alphavantage): add Alpha Vantage integration - #682

Merged
devjain32 merged 7 commits into
corsairdev:mainfrom
Agam00:feat/alphavantage
Aug 13, 2026
Merged

feat(alphavantage): add Alpha Vantage integration#682
devjain32 merged 7 commits into
corsairdev:mainfrom
Agam00:feat/alphavantage

Conversation

@Agam00

@Agam00 Agam00 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Description

Adds an Alpha Vantage integration implemented against the Alpha Vantage market
data API.

Fixes #681

56 operations across 9 resource groups, each with zod input and output
schemas, a declared risk level and a description. This is the full 56-op surface
listed on corsair.dev/oss/alpha_vantage, with no additions:

Group Ops Operations
timeSeries 9 intraday, intradayExtended, daily, weekly, weeklyAdjusted, monthly, monthlyAdjusted, globalQuote, realtimeBulkQuotes
market 5 symbolSearch, status, topGainersLosers, listingStatus, sector
fundamentals 10 companyOverview, incomeStatement, balanceSheet, cashFlow, earnings, earningsCalendar, earningsCallTranscript, ipoCalendar, dividends, splits
forex 5 exchangeRate, intraday, daily, weekly, monthly
crypto 4 intraday, daily, weekly, monthly
commodities 9 all, aluminum, brent, coffee, copper, corn, cotton, sugar, wheat
economic 10 realGdp, realGdpPerCapita, treasuryYield, federalFundsRate, cpi, inflation, retailSales, durables, nonfarmPayroll, unemployment
intelligence 3 newsSentiment, slidingWindowAnalytics, historicalOptions
technical 1 indicator

Every operation is a read. Alpha Vantage has no write surface at all — no
creates, no updates, no deletes — so no operation carries a write or
destructive risk level, and there are no triggers because the API has no
webhook, callback or streaming mechanism.

Auth

A single per-account API key passed as the apikey query parameter. There is no
OAuth flow and no refresh or expiry lifecycle, so this maps onto Corsair's
api_key auth type directly and oauth_2 is not offered.

The thing worth reviewing: errors arrive as HTTP 200

Alpha Vantage answers every request with HTTP 200, including failures, and
signals the failure with a key in the JSON body. Status codes are never
informative. assertNoAlphaVantageError in client.ts classifies the three
body shapes the provider actually uses and raises a typed error, so the handlers
in error-handlers.ts match on an explicit kind rather than on substring
guesswork:

Body key Meaning Classified as
Error Message malformed call — unknown function, missing parameter VALIDATION_ERROR
Note call-frequency limit, clears within a minute RATE_LIMIT_ERROR (retried)
Information containing "premium endpoint" plan limitation PERMISSION_ERROR
Information otherwise daily allowance exhausted RATE_LIMIT_ERROR (barely retried)

Two follow-on consequences, both verified against the live API rather than
inferred from the docs:

  • An unknown symbol is not an error. GLOBAL_QUOTE&symbol=ZZZZ_NOPE returns
    {"Global Quote": {}} — a well-formed envelope with nothing in it. Emptiness
    is therefore detected per response shape in endpoints/shared.ts and raised as
    an explicit not-found, rather than silently returning an empty object to the
    caller.
  • An invalid API key is not rejected. A key of
    THIS_KEY_IS_NOT_VALID_AT_ALL returned full live data, HTTP 200. There is in
    practice no auth-failure path on the query endpoint. AUTH_ERROR is kept and
    documented as defensive so that a transport-level 401, or a future change on
    the provider's side, is still classified rather than falling through to
    DEFAULT — but reviewers should know it is currently unreachable rather than
    assume it was tested.

Three operations return CSV, not JSON

LISTING_STATUS, EARNINGS_CALENDAR and IPO_CALENDAR are served as
Content-Type: application/x-download. They cannot use the shared JSON
transport, so makeAlphaVantageCsvRequest fetches them as text and decodes them
into rows. The CSV splitter handles quoted fields containing commas — Alpha
Vantage quotes company names such as "Alphabet, Inc.", and a naive
split(',') corrupts every row after the first one.

This is the same class of problem as the getResponseBody note in #672: the
shared request path assumes a JSON body and logs a caught SyntaxError when it
does not get one.

Six operations are premium-gated — including all intraday data

Verified against the live API on 2026-08-13 with a free-tier key. Each of these
answers with {"Information": "... This is a premium endpoint ..."} and
HTTP 200:

Operation Provider function
timeSeries.intraday TIME_SERIES_INTRADAY
timeSeries.intradayExtended TIME_SERIES_INTRADAY
forex.intraday FX_INTRADAY
crypto.intraday CRYPTO_INTRADAY
timeSeries.realtimeBulkQuotes REALTIME_BULK_QUOTES
intelligence.historicalOptions HISTORICAL_OPTIONS

In short: everything intraday, plus bulk quotes and the options chain. The
daily, weekly and monthly variants are all free, in every asset class. This is
not documented prominently and is easy to discover only after wiring an
operation up, so each of the six carries [PREMIUM PLAN] in its registry
description and a note at its handler.

They are implemented and covered by mocked tests, including a test asserting
that the premium notice is classified as PERMISSION_ERROR and not as a
rate limit — both arrive as an Information body and only the wording separates
them, so confusing the two would make the client retry something that can never
succeed.

The four intraday operations return the ordinary series envelope, confirmed from
their daily and weekly siblings, so their schemas are not guesswork. The other
two are different: their shapes could not be observed at all, and for bulk quotes
the provider explicitly warns that the sample payload accompanying the notice is
artificial. Those two are the only schemas in this PR modelled from the
documentation rather than a real response, and that is stated in types.ts at
the definitions. I did not want an invented sample payload silently becoming the
declared contract.

Other provider quirks encoded here

  • SECTOR is deprecated upstream and now answers with an empty object. It
    is implemented because the catalog lists it; the empty body is returned with a
    warning rather than being reported as an error, because that is the endpoint's
    actual behaviour and not a failure of the call.
  • TIME_SERIES_INTRADAY_EXTENDED has been folded into TIME_SERIES_INTRADAY
    via its month parameter. The operation is kept and the legacy slice
    argument (year1month1year2month12) is translated to the equivalent
    month.
  • Catalog names differ from provider function names for three operations:
    COMPANY_OVERVIEWOVERVIEW, GET_DIVIDENDSDIVIDENDS,
    GET_HISTORICAL_OPTIONSHISTORICAL_OPTIONS.
  • GET_SLIDING_WINDOW_ANALYTICS is on a different host
    alphavantageapi.co, addressed by path rather than a function parameter,
    with upper-case query parameters.
  • Meta Data key punctuation is inconsistent: price series use
    "1. Information" (period), technical indicators use "1: Symbol" (colon),
    and indicator meta mixes strings with numbers. The schemas do not assume one
    convention.
  • Numbers are strings throughout ("185.9200"). They are kept as strings
    rather than coerced, so a price is never silently altered by a float
    conversion and the caller decides how to parse.
  • The catalog omits WTI crude and natural gas even though Alpha Vantage
    publishes both. This matches the catalog rather than adding them.

Schema design

Two shared envelopes carry most of the surface:

  • IndicatorSeriesSchema{name, interval, unit, data[{date, value}]}. All
    nine commodities and all ten economic indicators return exactly this, so those
    19 operations are built from a single factory in
    endpoints/indicator-series.ts rather than nineteen near-identical blocks.
  • SeriesEnvelopeSchema — a Meta Data block plus one series object whose key
    names the series. Because that key varies with the request, the shape uses
    catchall rather than enumerating every possible name, which still validates
    the series contents.

Only security reference data is persisted (symbols: ticker, name, exchange,
asset type, status). Everything else Alpha Vantage returns is a price or an
indicator that is stale the moment it is stored, so caching it would be actively
harmful. The symbol mapping is the identifier every other operation needs, it
changes only when a security lists or delists, and the free tier allows just 25
requests per day — so resolving a ticker from cache rather than spending a
request on SYMBOL_SEARCH or the ~1 MB LISTING_STATUS download is a real
saving. Nothing is ever evicted: a delisted security is reported as Delisted
rather than disappearing, so the row stays with its status updated.

datatype is deliberately not exposed as an input. Alpha Vantage uses it to
switch a response between JSON and CSV, and letting a caller ask for CSV on a
JSON operation would return something the declared output schema cannot
describe.

  • No new third-party dependencies.

Checklist

  • I have run pnpm lint and all checks pass
  • I have run pnpm typecheck and there are no TypeScript errors
  • I have run pnpm build and all packages build successfully
  • I have run pnpm test and all tests pass
  • I have added or updated tests where applicable
  • I have added or updated necessary documentation

Screenshots / Demos

131 tests total — 124 CI-safe + 7 live.

image

The 124 CI-safe tests (client.test.ts, schema.test.ts, endpoints.test.ts)
cover query construction, all three error classifications, CSV decoding
including quoted fields, all 56 endpoint wrappers and the provider function each
one calls, the premium-notice handling for the six gated operations, the
emptiness checks, and the symbol cache writes — with the network mocked.

schema.test.ts validates the declared schemas against payloads captured from
the live API
, trimmed for length but otherwise unedited, rather than against
payloads transcribed from the documentation. Given how inconsistent Alpha
Vantage's key naming is, that distinction is the difference between a schema
that works and one that only looks right.

integration.test.ts runs against the real API and performs genuine round
trips: a quote, a daily series, a company overview (asserting the cache write),
a currency exchange rate, a commodity series, a symbol search, and the
unknown-ticker case that proves the empty envelope is turned into a not-found.
Seven requests, each chosen to exercise a response shape no other request
covers, paced at 1.2s — the free tier allows only 25 requests per day.

Additional Notes

  • integration.test.ts is named to match the CI exclusion in pr-checks.yml, so
    it never runs without credentials. It also self-skips when
    ALPHAVANTAGE_API_KEY is absent. Run it locally with:
    ALPHAVANTAGE_API_KEY=<key> pnpm exec jest integration
  • Because every operation is a read, the live suite creates nothing and needs no
    cleanup — unlike a CRUD provider, there is no teardown to get wrong.
  • The plugin is not registered in demo/testing/. CONTRIBUTING.md asks for
    that, but R1 in PLUGIN_PR_RULES.md restricts a plugin PR to
    packages/<plugin>/**, the constants.ts registration and pnpm-lock.yaml,
    so committing it would fail the scope gate. Live verification lives in
    integration.test.ts instead. Flagging again in case the two documents should
    be reconciled.
  • Anyone testing this should know the free tier is 25 requests per day, not
    per minute — it is easy to exhaust it and then read the resulting
    Information body as a bug. Alpha Vantage grants unlimited access to verified
    open-source projects on request.

Summary by CodeRabbit

  • New Features
    • Added Alpha Vantage integration with API-key authentication and read-only access.
    • Added time series, market data, fundamentals, forex, crypto, commodities, economic indicators, intelligence, and technical analysis.
    • Added typed validation, CSV support, symbol search, company and symbol caching, and audit logging.
    • Added retries and clear handling for rate limits, premium restrictions, authentication failures, missing data, and network errors.
  • Tests
    • Added comprehensive mocked, schema, and optional live integration coverage.

@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@Agam00 is attempting to deploy a commit to the corsair Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added a complete Alpha Vantage provider integration with typed schemas, 56 read-only endpoints, JSON and CSV transport, API-key authentication, error handling, symbol caching, audit logging, and test coverage.

Changes

Alpha Vantage integration

Layer / File(s) Summary
Contracts and plugin registration
packages/alphavantage/endpoints/types.ts, packages/alphavantage/index.ts, packages/alphavantage/schema/*, packages/alphavantage/webhooks/*, packages/corsair/core/constants.ts
Defines endpoint schemas, plugin bindings, authentication, persistence schemas, empty webhook types, package exports, and provider registration.
Transport and provider error handling
packages/alphavantage/client.ts, packages/alphavantage/error-handlers.ts, packages/alphavantage/client.test.ts
Adds JSON, analytics, and CSV requests with retries, error classification, CSV parsing, retry metadata, API-key sanitization, and transport tests.
Shared endpoint runtime and persistence
packages/alphavantage/endpoints/shared.ts, packages/alphavantage/endpoints/logging.ts, packages/alphavantage/endpoints/persist.ts, packages/alphavantage/endpoints/indicator-series.ts
Adds query serialization, empty-result validation, audit payload construction, indicator-series handling, and tolerant caching.
Core endpoint operations
packages/alphavantage/endpoints/time-series.ts, packages/alphavantage/endpoints/market.ts, packages/alphavantage/endpoints/forex.ts, packages/alphavantage/endpoints/crypto.ts, packages/alphavantage/endpoints/commodities.ts, packages/alphavantage/endpoints/economic.ts
Adds time-series, market, forex, crypto, commodity, and economic handlers.
Advanced endpoint operations
packages/alphavantage/endpoints/fundamentals.ts, packages/alphavantage/endpoints/intelligence.ts, packages/alphavantage/endpoints/technical.ts
Adds fundamentals, intelligence, technical, analytics, premium, and CSV-backed handlers.
Validation and package support
packages/alphavantage/*test.ts, packages/alphavantage/jest.config.cjs, packages/alphavantage/package.json, packages/alphavantage/tsconfig.json, packages/alphavantage/tsup.config.ts
Adds endpoint, schema, and live integration tests, plus package, Jest, TypeScript, and build configuration.

Estimated code review effort: 5 (Critical) | ~120 minutes

Mergeability Score: 🟡 Moderate · up to 43f41

Technical-indicator requests can currently omit provider-required parameters, causing validation failures instead of valid results. The input contract and associated tests should be corrected before merge; the future-dated provider verification note also needs owner awareness.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant AlphaVantageEndpoint
  participant AlphaVantageClient
  participant AlphaVantageAPI
  participant ErrorHandlers
  Caller->>AlphaVantageEndpoint: invoke typed operation
  AlphaVantageEndpoint->>AlphaVantageClient: build provider request
  AlphaVantageClient->>AlphaVantageAPI: send authenticated JSON or CSV request
  AlphaVantageAPI-->>AlphaVantageClient: return provider response
  AlphaVantageClient->>ErrorHandlers: classify provider or transport error
  AlphaVantageClient-->>AlphaVantageEndpoint: return parsed result or typed error
  AlphaVantageEndpoint-->>Caller: return validated endpoint output
Loading

Possibly related PRs

  • corsairdev/corsair#477: Adds a first-class provider plugin with provider registration.
  • corsairdev/corsair#648: Adds a complete provider plugin with analogous client, endpoint, schema, error-handler, and test structures.
  • corsairdev/corsair#651: Adds a structurally similar provider plugin with client, endpoint, schema, persistence, and error-handling layers.

Suggested reviewers: devjain32

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding the Alpha Vantage integration.
Linked Issues check ✅ Passed The changes implement the requested 56 read-only Alpha Vantage operations, API-key authentication, schemas, error handling, CSV support, caching, and provider-specific behavior [#681].
Out of Scope Changes check ✅ Passed The code, tests, package configuration, schemas, persistence helpers, and provider registration all directly support the Alpha Vantage integration scope [#681].
Docstring Coverage ✅ Passed Docstring coverage is 86.67% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the core Changes in packages/corsair label Aug 12, 2026
@Agam00
Agam00 marked this pull request as ready for review August 12, 2026 20:36
@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The Alpha Vantage plugin adds 56 read-only market-data operations across nine resource groups, API-key authentication, typed schemas, provider-specific error handling, CSV decoding, selective persistence, and test coverage.

  • Adds JSON and CSV transports, including HTTP-200 provider error-envelope classification and redaction of API keys from transport errors.
  • Adds market, fundamentals, time-series, forex, cryptocurrency, commodity, economic, intelligence, and technical-analysis endpoints.
  • Registers the plugin with Corsair and provides mocked schema, endpoint, transport, and optional live integration tests.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/alphavantage/client.ts Implements JSON, analytics, and single-attempt CSV transports with provider-envelope classification, bounded retry metadata, and API-key redaction.
packages/alphavantage/error-handlers.ts Classifies provider and transport failures into rate-limit, permission, authentication, validation, not-found, network, and default policies.
packages/alphavantage/endpoints/types.ts Declares the zod input and output contracts for the complete 56-operation endpoint surface.
packages/alphavantage/index.ts Registers endpoint groups, schemas, authentication, metadata, persistence entities, and error handlers as a Corsair plugin.
packages/alphavantage/client.test.ts Covers request construction, provider error envelopes, CSV parsing, single-layer throttling behavior, bounded Retry-After metadata, and credential redaction.
packages/alphavantage/endpoints.test.ts Exercises all declared operations, provider function mappings, special query transformations, empty responses, premium notices, caching, and audit logging.
packages/corsair/core/constants.ts Registers Alpha Vantage in the shared plugin constants.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Caller[Bound Alpha Vantage endpoint] --> Kind{Response format}
  Kind -->|JSON| Shared[Shared Corsair HTTP transport]
  Kind -->|CSV| Csv[Single-fetch CSV transport]
  Shared --> Envelope{Provider error envelope?}
  Csv --> Status{HTTP response successful?}
  Status -->|No| ApiError[Sanitized ApiError]
  Status -->|Yes| CsvEnvelope{JSON error envelope?}
  CsvEnvelope -->|No| Parse[Parse CSV rows]
  CsvEnvelope -->|Yes| ProviderError[Typed Alpha Vantage error]
  Envelope -->|No| Data[Validate and return data]
  Envelope -->|Yes| ProviderError
  ApiError --> Handlers[Plugin error handlers]
  ProviderError --> Handlers
  Handlers --> Retry{Retryable rate limit?}
  Retry -->|Yes| Caller
  Retry -->|No| Surface[Surface classified failure]
Loading

Reviews (6): Last reviewed commit: "fix(alphavantage): cap Retry-After; requ..." | Re-trigger Greptile

Comment thread packages/alphavantage/client.ts Outdated
@github-actions

Copy link
Copy Markdown

Plugin PR scorecard — packages/alphavantage

Check Status Notes
R1 — Scope: plugin files only
R2 — Tests with assertions
R3 — Description complete
R3 — Linked issue / claim
R4 — Demo video / recording

Rules: PLUGIN_PR_RULES.md · re-runs on every push

@github-actions

Copy link
Copy Markdown

Hey @Agam00, thanks for the contribution! 🏴‍☠️ Before a maintainer reviews, please fix the items below — the review re-runs automatically on your next push.

Must fix

  • P1 packages/alphavantage/client.ts:277CSV transport accepts HTTP failures
    If a CSV endpoint or intermediary returns a non-2xx HTML or plain-text response, this path parses the error body as CSV and resolves successfully, causing callers to receive malformed rows while transport-level 429 responses bypass the configured retry handler.

Rule Used: Every endpoint must validate inputs and outputs wi... (source)

Knowledge Base Used: The provider-plugin package pattern

If anything remains after your next push, a bot commit will clean it up; a maintainer always does the final review and merge.

@github-actions github-actions Bot added the bot:round-1 Review bot posted consolidated findings label Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
packages/alphavantage/jest.config.cjs (1)

5-10: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: drop the scaffold entries that this package does not use.

This package has no tests/, plugins/, or setup/ directories, and no YAML fixtures. The extra testMatch patterns and the YAML transform therefore never apply. Removing them shortens the config. Keep them if the plugin scaffold template requires an identical config across packages.

Also applies to: 20-22

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/alphavantage/jest.config.cjs` around lines 5 - 10, Optionally
simplify the Jest configuration by removing the unused tests/, plugins/, and
setup/ testMatch patterns, along with the YAML transform entries referenced in
the same config. Preserve them only if the plugin scaffold requires identical
configuration across packages.
🔇 Additional comments (38)
packages/alphavantage/endpoints/shared.ts (1)

13-88: LGTM!

packages/alphavantage/endpoints/logging.ts (1)

12-30: LGTM!

packages/alphavantage/endpoints/persist.ts (1)

44-54: LGTM!

packages/alphavantage/endpoints/indicator-series.ts (1)

18-40: LGTM!

packages/alphavantage/endpoints/time-series.ts (1)

24-280: LGTM!

packages/alphavantage/endpoints/market.ts (1)

13-145: LGTM!

packages/alphavantage/endpoints/forex.ts (1)

8-169: LGTM!

packages/alphavantage/endpoints/crypto.ts (1)

8-128: LGTM!

packages/alphavantage/endpoints/economic.ts (1)

17-67: LGTM!

packages/alphavantage/endpoints/commodities.ts (1)

4-42: LGTM!

packages/alphavantage/endpoints/types.ts (2)

306-331: 🗄️ Data Integrity & Integration

⚠️ Unverified finding
Sandbox verification was unavailable.

Verify that .refine()-wrapped input schemas are accepted by the plugin contract.

intelligenceNewsSentiment and technicalIndicator are the only two input schemas that are not plain ZodObject instances. RequiredPluginEndpointSchemas, the permissions type, and any consumer that reads .shape (tool/MCP generation, form rendering) can reject or silently mishandle a refined schema.

Run the following script to check the contract and the consumers:

Also applies to: 356-398


60-94: 📐 Maintainability & Code Quality

⚠️ Unverified finding
Sandbox verification was unavailable.

Confirm the declared Zod major version supports these APIs.

.loose(), the two-argument z.record(keySchema, valueSchema) form, and z.enum() on a readonly tuple are Zod 4 APIs. Zod 3 uses .passthrough() and a different z.record arity.

Run the following script to confirm the declared version:

Also applies to: 100-106

packages/alphavantage/schema/database.ts (1)

20-33: LGTM!

packages/alphavantage/schema/index.ts (1)

3-8: LGTM!

packages/alphavantage/index.ts (2)

134-209: LGTM!

Also applies to: 456-688


749-760: 🩺 Stability & Availability

⚠️ Unverified finding
Sandbox verification was unavailable.

Verify the empty-string fallback in keyBuilder.

If no key resolves, keyBuilder returns ''. The request then goes out with apikey=, and Alpha Vantage answers HTTP 200 with an Error Message body. The caller sees a validation error rather than a missing-credential error, and one request of the 25-per-day allowance is spent.

Run the following script to check how other plugins handle an unresolved key:

packages/alphavantage/webhooks/index.ts (1)

1-1: LGTM!

packages/alphavantage/webhooks/types.ts (1)

9-10: LGTM!

packages/alphavantage/endpoints/index.ts (1)

1-21: LGTM!

packages/corsair/core/constants.ts (1)

28-28: LGTM!

Also applies to: 149-149, 277-277

packages/alphavantage/client.ts (1)

78-115: LGTM!

packages/alphavantage/error-handlers.ts (2)

99-109: 🎯 Functional Correctness

⚠️ Unverified finding
Sandbox verification was unavailable.

Verify handler precedence for an invalid API key.

The client throws invalid_request for any Error Message body. An invalid key produces the message Alpha Vantage rejected the request: the parameter apikey is invalid. That message matches AUTH_ERROR by substring, and the same error matches VALIDATION_ERROR by kind. The resulting classification depends on the order in which the runtime evaluates the handlers.

Run the following script to confirm the evaluation order:

Also applies to: 126-132


32-62: LGTM!

Also applies to: 68-90, 165-186

packages/alphavantage/client.test.ts (1)

56-96: LGTM!

Also applies to: 98-163

packages/alphavantage/endpoints/fundamentals.ts (2)

15-38: LGTM!

Also applies to: 41-56, 59-74, 77-94, 97-114, 200-217, 220-237


121-136: 🗄️ Data Integrity & Integration

⚠️ Unverified finding
Sandbox verification was unavailable.

Confirm that empty CSV results are intentional successes.

earningsCalendar and ipoCalendar skip the assertNotEmpty check that the JSON operations apply. An empty calendar is a valid provider answer, so returning [] looks correct. A CSV body that the provider rejects (for example a plain-text notice) must not decode into zero rows and then be reported as a successful empty result. Verify that makeAlphaVantageCsvRequest classifies notice and error bodies before parsing.

Also applies to: 170-192

packages/alphavantage/endpoints/intelligence.ts (1)

19-44: LGTM!

Also applies to: 55-83, 91-108

packages/alphavantage/endpoints/technical.ts (1)

30-43: 🔒 Security & Privacy

⚠️ Unverified finding
Sandbox verification was unavailable.

Verify that extra_params cannot set function or apikey.

The core parameters are spread last, so extra_params cannot override symbol, interval, time_period, series_type, or month. function and apikey are not core parameters here. The client adds them. If the client merges this query after setting apikey, a caller-supplied extra_params.apikey can replace the account key or produce a duplicate parameter. Confirm the merge order in makeAlphaVantageRequest, or reject reserved keys in the technicalIndicator input schema.

packages/alphavantage/endpoints.test.ts (1)

136-560: LGTM!

Also applies to: 564-641, 643-700, 702-765, 767-899

packages/alphavantage/schema.test.ts (1)

13-323: LGTM!

Also applies to: 325-440

packages/alphavantage/integration.test.ts (2)

1-27: 📐 Maintainability & Code Quality

⚠️ Unverified finding
Sandbox verification was unavailable.

Verify the claimed CI exclusion.

The header states that this filename matches an exclusion in .github/workflows/pr-checks.yml. The describeLive guard already prevents live calls without a key, so CI stays safe either way. Confirm that the workflow pattern really excludes integration.test.ts, otherwise the comment misleads later maintainers.


29-131: LGTM!

packages/alphavantage/package.json (2)

16-20: 📐 Maintainability & Code Quality

⚠️ Unverified finding
Sandbox verification was unavailable.

Confirm the build script matches the other plugin packages.

rm -rf dist does not run in a Windows shell such as PowerShell. The PR screenshot shows development on Windows. If sibling plugins use the same script, keep it for consistency. If they use a portable cleaner, align with them.


1-15: LGTM!

Also applies to: 21-44

packages/alphavantage/jest.config.cjs (1)

1-4: LGTM!

Also applies to: 11-19, 23-55

packages/alphavantage/tsconfig.json (2)

17-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

⚠️ Unverified finding
Sandbox verification was unavailable.

Exclude test and config files from the declaration build.

include: ["./**/*"] with emitDeclarationOnly emits declarations for endpoints.test.ts, schema.test.ts, integration.test.ts, and tsup.config.ts into dist. package.json publishes dist, so those declarations ship to consumers. Exclude them, unless every plugin package intentionally uses the same include list.

♻️ Proposed exclude list
   "include": ["./**/*"],
-  "exclude": ["dist", "node_modules"]
+  "exclude": [
+    "dist",
+    "node_modules",
+    "**/*.test.ts",
+    "tsup.config.ts"
+  ],

1-16: LGTM!

Also applies to: 19-20

packages/alphavantage/tsup.config.ts (1)

1-15: LGTM!

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/alphavantage/client.ts`:
- Around line 272-292: Update makeAlphaVantageCsvRequest in
packages/alphavantage/client.ts (lines 272-292) to pass a timeout-backed abort
signal to fetch and reject non-2xx responses before parseCsv, while preserving
the existing CSV error-envelope handling. Add a test in
packages/alphavantage/client.test.ts (lines 200-223) mocking a 503 text response
and assert that makeAlphaVantageCsvRequest rejects rather than returning rows.

In `@packages/alphavantage/endpoints.test.ts`:
- Around line 901-910: Update the “does not record the free-text search term”
test to mock corsair/core’s logEventFromContext near the existing imports,
capture its payload, and assert the keywords value is absent from that payload.
Remove the ineffective lastUrl assertion while preserving the existing
Market.symbolSearch invocation.

In `@packages/alphavantage/endpoints/persist.ts`:
- Around line 57-65: Update cacheSymbols to avoid sequentially awaiting every
cacheSymbol write for large symbol lists. Use bounded concurrency or an existing
bulk-upsert capability while preserving the current early return and best-effort
caching behavior; anchor the change in cacheSymbols and cacheSymbol.

In `@packages/alphavantage/endpoints/types.ts`:
- Around line 363-366: Update the indicator validation in the technical endpoint
schema to allow digits in Alpha Vantage function names such as T3, while
retaining the existing uppercase-letter and underscore constraints and error
message context.

---

Nitpick comments:
In `@packages/alphavantage/jest.config.cjs`:
- Around line 5-10: Optionally simplify the Jest configuration by removing the
unused tests/, plugins/, and setup/ testMatch patterns, along with the YAML
transform entries referenced in the same config. Preserve them only if the
plugin scaffold requires identical configuration across packages.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c77086f-879c-4ba7-9012-090ab608865b

📥 Commits

Reviewing files that changed from the base of the PR and between 8c6ea9e and eeb7d40.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (31)
  • packages/alphavantage/client.test.ts
  • packages/alphavantage/client.ts
  • packages/alphavantage/endpoints.test.ts
  • packages/alphavantage/endpoints/commodities.ts
  • packages/alphavantage/endpoints/crypto.ts
  • packages/alphavantage/endpoints/economic.ts
  • packages/alphavantage/endpoints/forex.ts
  • packages/alphavantage/endpoints/fundamentals.ts
  • packages/alphavantage/endpoints/index.ts
  • packages/alphavantage/endpoints/indicator-series.ts
  • packages/alphavantage/endpoints/intelligence.ts
  • packages/alphavantage/endpoints/logging.ts
  • packages/alphavantage/endpoints/market.ts
  • packages/alphavantage/endpoints/persist.ts
  • packages/alphavantage/endpoints/shared.ts
  • packages/alphavantage/endpoints/technical.ts
  • packages/alphavantage/endpoints/time-series.ts
  • packages/alphavantage/endpoints/types.ts
  • packages/alphavantage/error-handlers.ts
  • packages/alphavantage/index.ts
  • packages/alphavantage/integration.test.ts
  • packages/alphavantage/jest.config.cjs
  • packages/alphavantage/package.json
  • packages/alphavantage/schema.test.ts
  • packages/alphavantage/schema/database.ts
  • packages/alphavantage/schema/index.ts
  • packages/alphavantage/tsconfig.json
  • packages/alphavantage/tsup.config.ts
  • packages/alphavantage/webhooks/index.ts
  • packages/alphavantage/webhooks/types.ts
  • packages/corsair/core/constants.ts

Comment thread packages/alphavantage/client.ts Outdated
Comment thread packages/alphavantage/endpoints.test.ts
Comment thread packages/alphavantage/endpoints/persist.ts
Comment thread packages/alphavantage/endpoints/types.ts Outdated
@Agam00

Agam00 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

@greptile review

@github-actions github-actions Bot added the bot:round-2 Review bot pushed an automated fix label Aug 12, 2026
@github-actions

Copy link
Copy Markdown

Remaining findings are being fixed by a bot commit — it will be re-reviewed automatically.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/alphavantage/client.ts (1)

333-346: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

The CSV path parses Retry-After but never retries.

makeAlphaVantageRequest and makeAlphaVantageAnalyticsRequest pass ALPHA_VANTAGE_RATE_LIMIT_CONFIG to the shared transport, so a 429 is retried there. makeAlphaVantageCsvRequest calls fetch directly, so a 429 rejects on the first attempt and the computed retryAfter only reaches the caller as metadata. This makes CSV operations less resilient than the JSON operations for the same rate limit.

Consider a small retry loop around the fetch call that honors parseRetryAfter, or document that CSV callers must handle 429 themselves.

Also applies to: 411-418

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/alphavantage/client.ts` around lines 333 - 346, Update
makeAlphaVantageCsvRequest to retry 429 responses using the existing
ALPHA_VANTAGE_RATE_LIMIT_CONFIG and parseRetryAfter behavior, rather than
returning immediately from the direct fetch path. Add a bounded retry loop
around fetch that honors the server’s retry delay and preserves the existing
response parsing and error behavior for non-retryable responses.
packages/alphavantage/endpoints/persist.ts (1)

67-80: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Bound the total number of cached rows, not only the concurrency.

The batch loop fixes the unbounded fan-out, but it does not bound total work. LISTING_STATUS returns tens of thousands of rows, so cacheSymbols still performs about symbols.length / 16 sequential batch round trips inside a read-only request. The caller still waits for all of them.

Since the cache is best-effort, cap the number of rows written per call, or move the write off the request path.

♻️ Proposed cap
+/** Upper bound on rows mirrored per call; the cache is best-effort. */
+const CACHE_WRITE_LIMIT = 2_000;
+
 /** Mirrors many securities, skipping rows with no ticker. */
 export async function cacheSymbols(
 	store: EntityStore<AlphaVantageSymbolEntity> | undefined,
 	symbols: readonly (SymbolCandidate | undefined | null)[],
 ) {
 	if (!store) return;
 
-	for (let i = 0; i < symbols.length; i += CACHE_WRITE_CONCURRENCY) {
-		const batch = symbols.slice(i, i + CACHE_WRITE_CONCURRENCY);
+	const capped = symbols.slice(0, CACHE_WRITE_LIMIT);
+	for (let i = 0; i < capped.length; i += CACHE_WRITE_CONCURRENCY) {
+		const batch = capped.slice(i, i + CACHE_WRITE_CONCURRENCY);
 		// `cacheSymbol` swallows its own failures, so no write in a batch can
 		// reject and abandon the rest.
 		await Promise.all(batch.map((symbol) => cacheSymbol(store, symbol)));
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/alphavantage/endpoints/persist.ts` around lines 67 - 80, Update
cacheSymbols to cap the total number of rows processed per invocation, in
addition to the existing CACHE_WRITE_CONCURRENCY batching. Limit the input or
loop to the established maximum cache-row count, preserve skipping invalid
symbols and best-effort cacheSymbol behavior, and ensure callers no longer await
writes for the full symbols collection.
packages/alphavantage/endpoints.test.ts (1)

938-960: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Strengthen the news audit assertion.

The current assertion checks only string absence and the presence of the limit key. It does not verify the event type, status, or complete payload. A future change could add time_from or another caller-authored field and still pass.

Assert the latest mocked call directly and expect { limit: 5 }.

Proposed test assertion
-		const serialized = JSON.stringify(lastLoggedPayload());
-		expect(serialized).not.toContain('AAPL');
-		expect(serialized).not.toContain('TSLA');
-		expect(serialized).not.toContain('earnings');
-		expect(serialized).toContain('limit');
+		expect(mockLogEvent).toHaveBeenLastCalledWith(
+			expect.anything(),
+			'alphavantage.intelligence.newsSentiment',
+			{ limit: 5 },
+			'completed',
+		);

The expected allowlist is defined in packages/alphavantage/endpoints/intelligence.ts Lines 19-44.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/alphavantage/endpoints.test.ts` around lines 938 - 960, Strengthen
the test in the “does not record the tickers or topics a news query asked for”
case by asserting the latest mocked audit call directly, including its expected
event type and status, with the payload exactly equal to `{ limit: 5 }`. Replace
the serialized string checks with a complete-object assertion so any unapproved
caller-authored fields are rejected.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/alphavantage/client.ts`:
- Around line 377-393: Redact API keys from error bodies in both production and
test coverage: in packages/alphavantage/client.ts lines 377-393, pass the
truncated CSV response text through redactApiKeyInUrl before assigning body, and
update sanitizeApiError to apply the same redaction to string body values; in
packages/alphavantage/client.test.ts lines 254-265, make the mocked body echo
the request URI and assert that body does not contain TEST_KEY.

---

Nitpick comments:
In `@packages/alphavantage/client.ts`:
- Around line 333-346: Update makeAlphaVantageCsvRequest to retry 429 responses
using the existing ALPHA_VANTAGE_RATE_LIMIT_CONFIG and parseRetryAfter behavior,
rather than returning immediately from the direct fetch path. Add a bounded
retry loop around fetch that honors the server’s retry delay and preserves the
existing response parsing and error behavior for non-retryable responses.

In `@packages/alphavantage/endpoints.test.ts`:
- Around line 938-960: Strengthen the test in the “does not record the tickers
or topics a news query asked for” case by asserting the latest mocked audit call
directly, including its expected event type and status, with the payload exactly
equal to `{ limit: 5 }`. Replace the serialized string checks with a
complete-object assertion so any unapproved caller-authored fields are rejected.

In `@packages/alphavantage/endpoints/persist.ts`:
- Around line 67-80: Update cacheSymbols to cap the total number of rows
processed per invocation, in addition to the existing CACHE_WRITE_CONCURRENCY
batching. Limit the input or loop to the established maximum cache-row count,
preserve skipping invalid symbols and best-effort cacheSymbol behavior, and
ensure callers no longer await writes for the full symbols collection.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 91dc4569-6337-4b1e-99fe-d9cae499417e

📥 Commits

Reviewing files that changed from the base of the PR and between eeb7d40 and ebfc3d5.

📒 Files selected for processing (6)
  • packages/alphavantage/client.test.ts
  • packages/alphavantage/client.ts
  • packages/alphavantage/endpoints.test.ts
  • packages/alphavantage/endpoints/persist.ts
  • packages/alphavantage/endpoints/types.ts
  • packages/alphavantage/schema.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/alphavantage/schema.test.ts
  • packages/alphavantage/endpoints/types.ts

Comment thread packages/alphavantage/client.ts
Agam00 and others added 3 commits August 13, 2026 02:52
Lock the company cache to the 55 live OVERVIEW keys and stop extra_params from setting function, apikey, or datatype.
@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

@greptile review

Comment thread packages/alphavantage/client.ts Outdated
Comment thread packages/alphavantage/client.ts Outdated
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

Maintainer review needed

Automated rounds are exhausted. Remaining findings:

  • P1 packages/alphavantage/client.tsCSV retries multiply after exhaustion
    When a CSV endpoint repeatedly returns HTTP 429, this loop makes three attempts and then throws a status-429 ApiError that the endpoint error handler retries twice more, restarting the entire inner loop. A single operation therefore makes up to nine requests while throttled, and the outer retries honor the raw Retry-After value rather than this transport's five-second ceiling.

Knowledge Base Used: The provider-plugin package pattern

@github-actions github-actions Bot added the needs-maintainer Automated rounds exhausted - human review needed label Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/alphavantage/schema.test.ts (1)

453-460: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject incomplete technical-indicator requests.

The passing cases omit provider-required parameters. Alpha Vantage requires series_type for RSI and MACD. It requires time_period for STOCHRSI. packages/alphavantage/endpoints/technical.ts forwards these missing values, so the provider receives an invalid request. (alphavantage.co)

Update AlphaVantageEndpointInputSchemas.technicalIndicator to require parameters by indicator. Then change these cases to reject incomplete input.

  • packages/alphavantage/schema.test.ts#L453-L460: require series_type for RSI.
  • packages/alphavantage/schema.test.ts#L462-L468: require series_type for MACD.
  • packages/alphavantage/schema.test.ts#L482-L489: require both time_period and series_type for STOCHRSI.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/alphavantage/schema.test.ts` around lines 453 - 460, Update
AlphaVantageEndpointInputSchemas.technicalIndicator to enforce
indicator-specific required fields: series_type for RSI and MACD, and both
time_period and series_type for STOCHRSI. In
packages/alphavantage/schema.test.ts at lines 453-460, 462-468, and 482-489,
change the incomplete-input cases to assert rejection rather than successful
parsing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/alphavantage/schema/database.ts`:
- Around line 20-26: Update the provider-contract comments in database.ts for
both LISTING_STATUS and SYMBOL_SEARCH by replacing the future “live 2026-08-13”
verification claims with the actual verification date, or remove the date
annotations entirely.

---

Outside diff comments:
In `@packages/alphavantage/schema.test.ts`:
- Around line 453-460: Update
AlphaVantageEndpointInputSchemas.technicalIndicator to enforce
indicator-specific required fields: series_type for RSI and MACD, and both
time_period and series_type for STOCHRSI. In
packages/alphavantage/schema.test.ts at lines 453-460, 462-468, and 482-489,
change the incomplete-input cases to assert rejection rather than successful
parsing.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1b3061d0-b6ff-4f37-af47-198823f97d4e

📥 Commits

Reviewing files that changed from the base of the PR and between c407ec7 and 3fa1b5b.

📒 Files selected for processing (10)
  • packages/alphavantage/endpoints.test.ts
  • packages/alphavantage/endpoints/fundamentals.ts
  • packages/alphavantage/endpoints/market.ts
  • packages/alphavantage/endpoints/persist.ts
  • packages/alphavantage/endpoints/technical.ts
  • packages/alphavantage/endpoints/types.ts
  • packages/alphavantage/integration.test.ts
  • packages/alphavantage/schema.test.ts
  • packages/alphavantage/schema/database.ts
  • packages/alphavantage/schema/index.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/alphavantage/endpoints.test.ts
  • packages/alphavantage/integration.test.ts
  • packages/alphavantage/endpoints/market.ts
  • packages/alphavantage/schema/index.ts
  • packages/alphavantage/endpoints/types.ts
  • packages/alphavantage/endpoints/fundamentals.ts

Comment thread packages/alphavantage/schema/database.ts
@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

@greptile review

@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/alphavantage/endpoints/types.ts`:
- Around line 396-422: Update the indicator schema refinements in the visible
validation chain to include T3 in both the time_period and series_type
requirement lists, so validation rejects either missing parameter before
dispatch. Add schema tests covering T3 without time_period and T3 without
series_type.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fa2022e6-9bd4-49af-bea7-a0e44aded229

📥 Commits

Reviewing files that changed from the base of the PR and between 3fa1b5b and 43f410f.

📒 Files selected for processing (4)
  • packages/alphavantage/client.test.ts
  • packages/alphavantage/client.ts
  • packages/alphavantage/endpoints/types.ts
  • packages/alphavantage/schema.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/alphavantage/schema.test.ts
  • packages/alphavantage/client.ts

Comment thread packages/alphavantage/endpoints/types.ts
@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

@greptile review

@Dhirenderchoudhary

Copy link
Copy Markdown
Collaborator

FIxed and LGTM

Checked this against the live API. Company cache didn’t match real OVERVIEW, extra_params could override the key, and errors were leaking the apikey.

CSV was retrying twice and Retry-After could hang forever one layer now, 5s cap.

Also required time_period / series_type for RSI, MACD, STOCHRSI, and T3 so we don’t send broken calls.

@devjain32
devjain32 merged commit 1fc955a into corsairdev:main Aug 13, 2026
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:round-1 Review bot posted consolidated findings bot:round-2 Review bot pushed an automated fix core Changes in packages/corsair needs-maintainer Automated rounds exhausted - human review needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Alpha Vantage integration

3 participants